﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime;
using System.Runtime.InteropServices;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.Text;
using System.Threading;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Web.SessionState;
using System.Web.Services.Description;
using System.Xml.Serialization;

using PickGold.Arguments;
using PickGold.Base.Proxies;

namespace PickGold.Base.Remoting
{
	/// <summary>
	/// "C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\wsdl.exe" http://localhost:2222/ws.asmx?wsdl /language:c# /out:c:\temp\temp.cs
	/// </summary>
	class MethodInvokerWsClient : SoapHttpClientProtocol, IMethodInvoker
	{
		private static Hashtable InterfaceCache = new Hashtable();

		public static bool OnlyRemote = false;

		public MethodInvokerWsClient() : base() { }

		public MethodInvokerWsClient(string url) : base()
		{
			base.Url = url;
		}

		[SoapDocumentMethod("hsj://hong.shi.jin/Invoke", RequestNamespace = "hsj://hong.shi.jin/", ResponseNamespace = "hsj://hong.shi.jin/", Use = SoapBindingUse.Literal, ParameterStyle = SoapParameterStyle.Wrapped)]
		[return: XmlElement(DataType = "base64Binary")]
		public byte[] Invoke([XmlElement(DataType = "base64Binary")] byte[] message)
		{
			var rs = this.Invoke(MethodBase.GetCurrentMethod().Name, new object[] { message });
			if (rs == null || rs.Length == 0)
				return null;

			message = rs[0] as byte[];
			return message;
		}

		/// <remarks/>
		public IAsyncResult BeginInvoke(byte[] message, AsyncCallback callback, object asyncState)
		{
			return this.BeginInvoke("Invoke", new object[] { message }, callback, asyncState);
		}

		/// <remarks/>
		public new byte[] EndInvoke(IAsyncResult asyncResult)
		{
			var rs = base.EndInvoke(asyncResult);
			if (rs == null || rs.Length == 0)
				return null;

			return rs[0] as byte[];
		}

		/// <remarks/>
		public IAsyncResult BeginAsyncInvoke(byte[] message, AsyncCallback callback, object state)
		{
			return base.BeginInvoke("BeginAsyncInvoke", new object[] { message }, callback, state);
		}

		/// <remarks/>
		public byte[] EndAsyncInvoke(IAsyncResult result)
		{
			var rs = base.EndInvoke(result);
			if (rs == null || rs.Length == 0)
				return null;

			return rs[0] as byte[];
		}

		[SoapDocumentMethod("hsj://hong.shi.jin/GetDateTime", RequestNamespace = "hsj://hong.shi.jin/", ResponseNamespace = "hsj://hong.shi.jin/", Use = SoapBindingUse.Literal, ParameterStyle = SoapParameterStyle.Wrapped)]
		public DateTime GetDateTime(string dateTime)
		{
			var rs = this.Invoke(MethodBase.GetCurrentMethod().Name, new object[] { dateTime });
			if (rs == null || rs.Length == 0)
				return DateTime.MinValue;

			return (DateTime)rs[0];
		}

		public static object Create(Type type)
		{
			lock (Common.StaticCache.InnerForGetImplement)
			{
				if (Common.StaticCache.InnerForGetImplement.ContainsKey(type))
					return Common.StaticCache.InnerForGetImplement[type];

				var t = ImplementAttribute.GetImplementedType(type);
				if (t == null)
				{
					try
					{
						Common.StaticCache.InnerForGetImplement[type] = null;
					}
					catch (Exception x)
					{
						x.WriteEvent();
					}
					return null;
				}

				var o = t.GetInstance();
				try
				{
					Common.StaticCache.InnerForGetImplement[type] = o;
				}
				catch (Exception x)
				{
					x.WriteEvent();
				}
				return o;
			}
		}

		public static API Create<API>() where API : class
		{
			if (MethodInvokerWsClient.OnlyRemote)
				return default(API);

			var o = MethodInvokerWsClient.Create(typeof(API));
			if (o == null)
				return default(API);

			return (API)o;
		}
	}
}
